package net.gq.logistics.shiro;

import net.gq.logistics.pojo.User;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * @author ASUS
 * @date 2020/5/24
 */
public class MyFormAuthenticationFilter extends FormAuthenticationFilter {


    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        //从请求中获取Shiro的 主体
        Subject subject = getSubject(request, response);
        //从主体中获取Shiro框架的Session
        Session session = subject.getSession();
        //如果主体没有认证（Session中认证）并且 主体已经设置记住我了
        if (!subject.isAuthenticated() && subject.isRemembered()) {
            //获取主体的身份（从记住我的Cookie中获取的）
            User principal = (User) subject.getPrincipal();
            //将身份认证信息共享到 Session中:Session获取数据通过类型判断，和名称无关
            session.setAttribute("user", principal);
        }
        return subject.isAuthenticated() || subject.isRemembered();

    }

    /**
     * 1. 从请求对象中获取出验证码，从Session中获取出随机数
     * 2. 比较用户请求提交的验证码和Session中的随机数比对
     * <p>
     * 相同继续调用父类方法
     * 不相同：直接返回false，并且跳转到登录页面，共享错误信息
     *
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {

        //判断是否为登录请求
        if (isLoginRequest(request, response)) {

            //判断是否是post
            if (isLoginSubmission(request, response)) {

                //强转
                HttpServletRequest req = (HttpServletRequest) request;

                //1.获取请求对象的verifyCode的验证码参数
                String verifyCode = request.getParameter("verifyCode");

                //2.获取session
                String rand = (String) req.getSession().getAttribute("rand");

                if (StringUtils.isNotBlank(verifyCode)) {

                    if (!verifyCode.equalsIgnoreCase(rand)) {
                        //验证码错误
                        req.setAttribute("errorMsg","验证码错误！");

                        //跳转到登录界面
                        req.getRequestDispatcher("/login.jsp").forward(request,response);
                        return false;
                    }



                }else {
                    //验证码不能为空
                    req.setAttribute("errorMsg","验证码不能为空！");

                    //跳转到登录界面
                    req.getRequestDispatcher("/login.jsp").forward(request,response);
                    return false;
                }


            }
        }

        //开始认证
        return super.onAccessDenied(request, response);
    }

    /**
     * 重写认证成功跳转问题
     *
     * @param token
     * @param subject
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @Override
    protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {

        WebUtils.getAndClearSavedRequest(request); //会清理原先地址

        WebUtils.redirectToSavedRequest(request, response, "/index.do");

        return false;
    }
}
